function seq_list = seqparse(seq_str)

% SEQPARSE - parse DATAC-style sequence command string
%
%    LIST = SEQPARSE(STR) parses the DATAC-style sequence command
%    string STR and returns a numeric sequence LIST specified by
%    the sequence command.

% By:   S.C. Molitor (smolitor@med.unc.edu)
% Date: January 12, 2000

% initialize outputs to prevent MATLAB errors

seq_list = [];

% validate arguments

if (nargin ~= 1)
   msgbox('Invalid number of arguments', 'SEQPARSE Error', 'warn');
   return
elseif (~ischar(seq_str))
   msgbox('STR must be a string', 'SEQPARSE Error', 'warn');
   return
end

% separate multiple sequences

rem_line = seq_str;
while (~isempty(rem_line))
   [token, rem_line] = strtok(rem_line, ', ');
   if (isempty(token))
      break
   else
      seq_list = [seq_list get_seq_list(token)];
   end
end
return



function [seq_list] = get_seq_list(seq_str);

% GET_SEQ_LIST - parse individual DATAC-style sequence command string

% initialize outputs to prevent MATLAB errors

seq_list = [];
rem_line = seq_str;

% obtain sequence parameter strings
% sequence command is of the form '<first>;<last>/<skip><char>'

[first_str, rem_line] = strtok(rem_line, ';');
[last_str, rem_line] = strtok(rem_line, ';/');
[skip_str, rem_line] = strtok(rem_line, '/');

% determine whether valid sequence command string was provided

if (~isempty(rem_line))
   msgbox(sprintf('Invalid sequence string ''%s''', seq_str), 'SEQPARSE Error', 'warn');
   return
elseif (isempty(first_str))
   msgbox(sprintf('First parameter in ''%s'' is missing', seq_str), 'SEQPARSE Error', 'warn');
   return
elseif (isempty(last_str) & ~isempty(skip_str))
   msgbox(sprintf('Last parameter in ''%s'' is missing', seq_str), 'SEQPARSE Error', 'warn');
   return
end

% obtain values for <first> & <last>

if (isempty(first_str))
   first_num = [];
else
   first_num = str2num(first_str);
end
if (isempty(last_str))
   last_num = [];
else
   last_num = str2num(last_str);
end

% obtain value for <skip>
% strip character ('r', 's', etc.) first

skip_arg = skip_str(isletter(skip_str));
skip_str = skip_str(~isletter(skip_str));
if (isempty(skip_str))
   skip_num = [];
else
   skip_num = str2num(skip_str);
end

% check for valid numeric parameters

if (~isempty(first_str) & isempty(first_num))
   msgbox(sprintf('First parameter ''%s'' in ''%s'' is not numeric', first_str, seq_str), 'SEQPARSE Error', 'warn');
   return
elseif (~isempty(last_str) & isempty(last_num))
   msgbox(sprintf('Last parameter ''%s'' in ''%s'' is not numeric', last_str, seq_str), 'SEQPARSE Error', 'warn');
   return
elseif (~isempty(skip_str) & isempty(skip_num))
   msgbox(sprintf('Skip parameter ''%s'' in ''%s'' is not numeric', skip_str, seq_str), 'SEQPARSE Error', 'warn');
   return
end

% generate sequence list based upon form of sequence string
% missing values determine form of string

if (isempty(last_num))			% 'XX'
   seq_list = first_num;
elseif (isempty(skip_num))		% 'XX;XX'
   seq_list = [first_num : last_num];
elseif (isempty(skip_arg))		% 'XX;XX/XX'
   seq_list = [first_num : skip_num : last_num];
else
   switch (skip_arg)		% skip argument determines how sequence is generated
   case {'a', 'd'}		% alternating sequences
      
      % skip parameter is length of sequence
      % fill sequence with first parameter
      
      skip_num = floor(skip_num);
      seq_list = zeros(1, skip_num) + first_num;
      
      % replace alternating values with last parameter
      
      if ((skip_arg == 'a') & (length(seq_list) >= 2))
         seq_list(2 : 2 : end) = last_num;
      elseif ((skip_arg == 'd') & (length(seq_list) >= 3))
         seq_list(2 : 4 : end) = last_num;
         seq_list(3 : 4 : end) = last_num;
      end
      
   case {'l', 's'}		% logarithmically-spaced steps
      
      % check for positive values
      % return if skip = 0 (no error, just empty)
      
      if (first_num <= 0)
         msgbox(sprintf('Cannot take LOG(%f) in ''%s''', first_num, seq_str), 'SEQPARSE Error', 'warn');
         return
      elseif (last_num <= 0)
         msgbox(sprintf('Cannot take LOG(%f) in ''%s''', last_num, seq_str), 'SEQPARSE Error', 'warn');
         return
      elseif (skip_num == 0)
         return
      end
      
      % create logarithmically-spaced sequence
      
      first_log = log(first_num);
      last_log = log(last_num);
      skip_log = (last_log - first_log) / skip_num;
      log_list = first_log : skip_log : last_log;
      seq_list = exp(log_list);
      
      % randomize order if specified
      
      if (skip_arg == 's')
         seq_list = seq_list(randperm(length(seq_list)));
      end
      
   otherwise				% linearly-spaced steps
      
      % create linearly-space sequence
      % randomize order if specified
      
      seq_list = [first_num : skip_num : last_num];
      if (skip_arg == 'r')
         seq_list = seq_list(randperm(length(seq_list)));
      end
   end
end
return
